-
Notifications
You must be signed in to change notification settings - Fork 373
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve scale handling for PrecisionModel #956
Conversation
I wonder if the inverse problem may occur as well: an integral grid size (e.g. 1000) would produce undesired "slop" when converted to a reciprocal scale factor? This might require building a fuzzer to test a lot of values to see if this occurs. It's possible that the guard digits in FP arithmetic will handle this problem. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks OK to me. How do we feel about the behaviour when gridSize is > 0 (1, 10, 100, etc)?
It seems to work. But perhaps should only do the integral test when the gridSize is < 1. If the gridSize > 1, I haven't seen this produce rounding issues. Perhaps that's because the scaling is cutting off digits before the decimal point, so the FP arithmetic works better? |
Seems ok to me, now I wonder how results compare with ST_SnapToGrid |
I will add that data as a test case. UpdateIndeed, this is exactly the same behaviour, and the new code will fix it.
|
c5c0733
to
3d19930
Compare
Also recently reported on postgis-users. |
Another quirk that could be worth fixing here or in a separate issue is
where the expected result should have been:
And what should happen with |
Good find. There are lots of examples of this occurring in |
@mwtoews This is a different problem, so should be a separate issue. (Is there already an issue for this?) Technically zero-length linestrings are invalid, but it seems good to bend the rules in this case.
Probably the latter - so as to not lose information. |
I have found a case where a large gridsize (100,000) causes rounding error when using the reciprocal scale factor. Using the gridsize 100,000 directly works:
Using the reciprocal scale factor of 0.00001 causes rounding error:
To resolve this, gridsizes > 1 need to be computed using the more stable arithmetic formula:
Also, it's best to move the integral rounding logic into |
88909c1
to
1bede1e
Compare
Problem
GEOS_setPrecision
accepts a parameter specifying the grid size of the desired precision. The most common usage is to reduce the number of decimal places in a geometry (e.g. to 3 decimal places). In this case, the grid size is a negative power of 10 (e.g. 0.001). However, this can result in inexact rounding of ordinate values.For example, this
geosop
command reproduces this PostGIS issue and shows how reducing the precision of a geometry using grid size 0.001 produces unwanted "extra decimals" (note that ingeosop
thereducePrecision
operation parameter is negative to indicate the value is a grid size):The same issue can happen when using a scale factor that is a negative power of 10:
Cause
There are two causes of this problem:
Because negative powers of 10 cannot be represented exactly in binary FP numbers this can cause the resulting "rounded" ordinate values to be inexact.
In contrast, if an integral scale factor is used directly, the rounding arithmetic is:
This produces the desired result:
Proposed Fix
This PR proposes a fix which has no impact on the GEOS API or semantics (and hence on downstream usage).
The fix does two things:
Almost all (or all?) uses of
GEOS_setPrecision
use either grid sizes equivalent to integral scale factors OR grid sizes which are obviously NOT integral (e.g. say0.5
), so the heuristic of deciding "close" is fine for practical purposes.In the very rare cases where both grid size and scale factor are fractional, the original values are used for scaling. Since they are fractional already, the output won't be exact in any case.
As a nice side effect, this fix allows dropping support for negative scale factors, which was introduced solely to accommodate the use of grid size rather than scale factor. (This PR will be extended to delete this code if that is agreed to).